﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Software41.Tracking.BAM;
using Microsoft.XLANGs.BaseTypes;
using Moq;
using System.IO;

namespace Software41.Tracking.BAM.Tests
{
    /// <summary>
    /// Summary description for ProcessInfoTests
    /// </summary>
    [TestClass]
    public class ProcessInfoTests
    {
        public ProcessInfoTests()
        {
            //
            // TODO: Add constructor logic here
            //
        }

        private TestContext testContextInstance;

        /// <summary>
        ///Gets or sets the test context which provides
        ///information about and functionality for the current test run.
        ///</summary>
        public TestContext TestContext
        {
            get
            {
                return testContextInstance;
            }
            set
            {
                testContextInstance = value;
            }
        }

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        #region Begin Tests
        [TestMethod]
        public void Process_Begin_Success()
        {
            //arrange
            string processName = "TestProcess1";
            string processId = Guid.NewGuid().ToString();

            Mock<IEventStream> eventStream = new Mock<IEventStream>(MockBehavior.Strict);
            eventStream.Setup(b => b.BeginActivity(ActivityType.ProcessTraceInfo.ToString(), processId));
            eventStream.Setup(b => b.UpdateActivity(ActivityType.ProcessTraceInfo.ToString(), processId, InfoBase.ACTIVITY_DATA_NAME, processName));
            eventStream.Setup(b => b.UpdateActivity(ActivityType.ProcessTraceInfo.ToString(), processId, InfoBase.ACTIVITY_DATA_BEGIN, It.IsAny<DateTime>()));

            //act
            var process = new ProcessTraceInfo(processName, processId, eventStream.Object);
            var actualProcessId = process.Begin();

            //Verify
            Assert.AreEqual(processId, actualProcessId);
            eventStream.VerifyAll();

        }

        [TestMethod]
        public void Process_Begin_StringData_Success()
        {
            //arrange
            string processName = "TestProcess1";
            string processId = Guid.NewGuid().ToString();
            string messageTitle = "SampleRequestMessage";
            string messageXml = "<Request>Here is our request xml</Request>";

            Mock<IEventStream> eventStream = new Mock<IEventStream>(MockBehavior.Strict);
            eventStream.Setup(b => b.BeginActivity(ActivityType.ProcessTraceInfo.ToString(), processId));
            eventStream.Setup(b => b.UpdateActivity(ActivityType.ProcessTraceInfo.ToString(), processId, InfoBase.ACTIVITY_DATA_NAME, processName));
            eventStream.Setup(b => b.UpdateActivity(ActivityType.ProcessTraceInfo.ToString(), processId, InfoBase.ACTIVITY_DATA_BEGIN, It.IsAny<DateTime>()));
            eventStream.Setup(b => b.AddReference(ActivityType.ProcessTraceInfo.ToString(), processId,
                                                    ActivityType.ProcessTraceInfo.ToString() + "Data-" + InfoBase.ACTIVITY_MSG_BEGIN_DATA, InfoBase.ACTIVITY_MSG_BEGIN_DATA,
                                                    messageTitle, messageXml));

            var msgDataLink = BAMLinkedDocUrlGenerator.GenerateLinkedDocUrl(ActivityType.ProcessTraceInfo.ToString(), processId, ActivityType.ProcessTraceInfo.ToString() + "Data-" + InfoBase.ACTIVITY_MSG_BEGIN_DATA);

            eventStream.Setup(b => b.AddReference(ActivityType.ProcessTraceInfo.ToString(), processId,
                                                    BAMLinkedDocUrlGenerator.BAM_DOCUMENT_URL,
                                                    messageTitle + " " + InfoBase.ACTIVITY_MSG_BEGIN_DATA,
                                                    msgDataLink));


            //act
            var process = new ProcessTraceInfo(processName, processId, eventStream.Object);
            var actualProcessId = process.Begin(messageTitle, messageXml);

            //Verify
            Assert.AreEqual(processId, actualProcessId);
            eventStream.VerifyAll();
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Process_Begin_StringData_Failure()
        {
            //arrange
            string processName = "TestProcess1";
            string processId = Guid.NewGuid().ToString();
            string messageDataName = null;
            string messageData = null;

            Mock<IEventStream> eventStream = new Mock<IEventStream>();

            //act
            var process = new ProcessTraceInfo(processName, processId, eventStream.Object);
            var actualProcessId = process.Begin(messageDataName, messageData);

        }

        #endregion

        #region End Tests


        [TestMethod]
        public void Process_End_Success()
        {
            //arrange
            string processName = "TestProcess1";
            string processId = Guid.NewGuid().ToString();

            Mock<IEventStream> eventStream = new Mock<IEventStream>(MockBehavior.Strict);
            eventStream.Setup(b => b.UpdateActivity(ActivityType.ProcessTraceInfo.ToString(), processId, InfoBase.ACTIVITY_DATA_SUCCESS, true));
            eventStream.Setup(b => b.UpdateActivity(ActivityType.ProcessTraceInfo.ToString(), processId, InfoBase.ACTIVITY_DATA_END, It.IsAny<DateTime>()));
            eventStream.Setup(b => b.EndActivity(ActivityType.ProcessTraceInfo.ToString(), processId));


            //act
            var process = new ProcessTraceInfo(processName, processId, eventStream.Object);
            process.End();

            //Verify
            eventStream.VerifyAll();

        }

        [TestMethod]
        public void Process_End_StringData_Success()
        {
            //arrange
            string processId = Guid.NewGuid().ToString();
            string messageTitle = "SampleResponseMessage";
            string messageXml = "<Response>Here is our response xml</Response>";

            Mock<IEventStream> eventStream = new Mock<IEventStream>(MockBehavior.Strict);
            eventStream.Setup(b => b.UpdateActivity(ActivityType.ProcessTraceInfo.ToString(), processId, InfoBase.ACTIVITY_DATA_SUCCESS, true));
            eventStream.Setup(b => b.UpdateActivity(ActivityType.ProcessTraceInfo.ToString(), processId, InfoBase.ACTIVITY_DATA_END, It.IsAny<DateTime>()));
            eventStream.Setup(b => b.EndActivity(ActivityType.ProcessTraceInfo.ToString(), processId));
            eventStream.Setup(b => b.AddReference(ActivityType.ProcessTraceInfo.ToString(), processId,
                                                    ActivityType.ProcessTraceInfo.ToString() + "Data-" + InfoBase.ACTIVITY_MSG_END_DATA, InfoBase.ACTIVITY_MSG_END_DATA,
                                                    messageTitle, messageXml));


            var msgDataLink = BAMLinkedDocUrlGenerator.GenerateLinkedDocUrl(ActivityType.ProcessTraceInfo.ToString(), processId, ActivityType.ProcessTraceInfo.ToString() + "Data-" + InfoBase.ACTIVITY_MSG_END_DATA);

            eventStream.Setup(b => b.AddReference(ActivityType.ProcessTraceInfo.ToString(), processId,
                                                    BAMLinkedDocUrlGenerator.BAM_DOCUMENT_URL,
                                                    messageTitle + " " + InfoBase.ACTIVITY_MSG_END_DATA,
                                                    msgDataLink));

            //act
            var process = new ProcessTraceInfo(processId, eventStream.Object);
            process.End(messageTitle, messageXml);

            //Verify
            eventStream.VerifyAll();
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void Process_End_StringData_Failure()
        {
            //arrange
            string processName = "TestProcess1";
            string processId = Guid.NewGuid().ToString();
            string messageDataName = null;
            string messageData = null;

            Mock<IEventStream> eventStream = new Mock<IEventStream>();

            //act
            var process = new ProcessTraceInfo(processName, processId, eventStream.Object);
            process.End(messageDataName, messageData);
        }

        #endregion

        
    }
}
